package com.yikome.product.controller;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections4.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.itmuch.lightsecurity.annotation.PreAuthorize;
import com.yikome.product.crawler.CrawlerProductService;
import com.yikome.product.dto.ProductAttributeValueCreateDTO;
import com.yikome.product.dto.ProductBatchEditDTO;
import com.yikome.product.dto.ProductDTO;
import com.yikome.product.dto.ProductEditDTO;
import com.yikome.product.dto.ProductSetEditDTO;
import com.yikome.product.entity.Product;
import com.yikome.product.entity.ProductComments;
import com.yikome.product.entity.ProductExt;
import com.yikome.product.repository.ProductExtRepository;
import com.yikome.product.request.CrawlerProductRequest;
import com.yikome.product.request.ProductRequest;
import com.yikome.product.service.ProductService;
import com.yikome.shop.entity.Shop;
import com.yikome.shop.service.ShopService;
import com.yikome.utils.AsyncCsvUtils;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequestMapping("/product")
public class ProductController {

	@Autowired
	private ProductService productService ; 
	
	@Autowired
	private ProductExtRepository productExtRepository ;
	
	@Autowired
	private CrawlerProductService crawlerProductService;
	
	@Autowired
	private ShopService shopService ; 
	
	
	@GetMapping("/list")
	@PreAuthorize("hasAnyRoles('admin', 'analysis', 'shop', 'affiliate')")
	public Page<ProductDTO> findProducts(@PageableDefault(sort = {"id"}, direction = Sort.Direction.DESC) Pageable pageable, ProductRequest productRequest){
		
		return productService.findProduct(productRequest, pageable);
		
	}
	
	@GetMapping("/list/export-fb")
	@PreAuthorize("hasAnyRoles('admin', 'analysis', 'shop', 'affiliate')")
	public String exportFbLists(ProductRequest productRequest){
		
		List<Map<String, Object>> fbLists = productService.exportFbLists(productRequest, PageRequest.of(0, 1000000, Sort.Direction.DESC, "id"));
		
		Shop shop = shopService.getRequestShop("yikome");
		
		List<Map<String, Object>> exportDatas = new ArrayList<>();
		for (Map<String, Object> map : fbLists) {
			Map<String, Object> tmpMap = new LinkedHashMap<>();
			tmpMap.put("id", Convert.toInt(map.get("id")));
			tmpMap.put("title", Convert.toStr(map.get("title")));
			tmpMap.put("description", Convert.toStr(map.get("description")));
			tmpMap.put("availability", "in stock");
			tmpMap.put("condition", "new");
			tmpMap.put("price", Convert.toBigDecimal(map.get("price")).multiply(shop.getExchangeRate()).setScale(0, BigDecimal.ROUND_DOWN) + " " + "TWD");
			tmpMap.put("link", "https://yikome.com/item/details.html?id=" + Convert.toInt(map.get("id")));
			tmpMap.put("image_link", StrUtil.prependIfMissing(Convert.toStr(map.get("image")), "https:", "https:", "http:"));
			tmpMap.put("brand", "yiko");
			tmpMap.put("inventory", 999);
			tmpMap.put("category_name", Convert.toStr(map.get("category_name")));
			exportDatas.add(tmpMap);
		}
		
		return AsyncCsvUtils.handleCsvDatas(exportDatas, "DPA商品数据");
	}
	
	@PostMapping("/create")
	@PreAuthorize("hasAnyRoles('admin','shop', 'affiliate')")
	public Boolean createProducts(@RequestBody CrawlerProductRequest crawlerProductRequest) throws InterruptedException{
		
		Preconditions.checkArgument(Lists.newArrayList("tmall" , "taobao" , "1688" , "aliexpress", "pdd").contains(crawlerProductRequest.getSourceType()), "不支持的类型...");
    	Preconditions.checkArgument(crawlerProductRequest.getProductIds() != null && !crawlerProductRequest.getProductIds().isEmpty(), "产品ID不能为空....");
    	
    	Set<String> productUrls = new LinkedHashSet<>();
    	
    	if(StrUtil.equalsIgnoreCase("tmall", crawlerProductRequest.getSourceType())) {
    		
    		for (String productId : crawlerProductRequest.getProductIds()) {
    			
    			List<ProductExt> productExts = productExtRepository.findExitsBySourceId(productId);
    			if(productExts == null || productExts.isEmpty())productUrls.add("https://api03.6bqb.com/tmall/detail?itemid=" + productId);
			}
    		crawlerProductService.crawler99TaoBaoAndTmallProduct(productUrls);
    		
    	}else if(StrUtil.equalsIgnoreCase("taobao", crawlerProductRequest.getSourceType())) {
    		
    		for (String productId : crawlerProductRequest.getProductIds()) {
    			
    			List<ProductExt> productExts = productExtRepository.findExitsBySourceId(productId);
    			
    			if(productExts == null || productExts.isEmpty())productUrls.add("https://api03.6bqb.com/taobao/detail?itemid=" + productId);
			}
    		crawlerProductService.crawler99TaoBaoAndTmallProduct(productUrls);
    		
    	}else if(StrUtil.equalsIgnoreCase("1688", crawlerProductRequest.getSourceType())) {
    		
    		for (String productId : crawlerProductRequest.getProductIds()) {
    			
    			List<ProductExt> productExts = productExtRepository.findExitsBySourceId(productId);
    			
    			if(productExts == null || productExts.isEmpty())productUrls.add("https://api03.6bqb.com/alibaba/detail?itemid=" + productId) ; 
			}
    		crawlerProductService.crawler991688Product(productUrls);
    		
    	}else if(StrUtil.equalsIgnoreCase("pdd", crawlerProductRequest.getSourceType())) {
    		
    		for (String productId : crawlerProductRequest.getProductIds()) {
    			
    			List<ProductExt> productExts = productExtRepository.findExitsBySourceId(productId);
    			
    			if(productExts == null || productExts.isEmpty())productUrls.add("http://api.youkezhushou.com/api/Pdd/detail?parm.itemid=" + productId) ; 
			}
    		crawlerProductService.crawlerykpddProduct(productUrls);
    	}
    	
    	return Boolean.TRUE;
	}
	
	@PutMapping("/price/1688")
	public Map<Long , String> update1688Price(){
		
		Map<Long , String> errors = new HashedMap<>();
		
		List<Product> products = productService.findAllProduct("1688");
		
		for (Product product : products) {
			try {
				log.info("update1688Price: {}" , product.getId());
				productService.update1688Price(product);
			}catch (Exception e) {
				errors.put(product.getId(), e.getMessage());
			}
		}
		
    	return errors;
	}
	
	@GetMapping("/{productId}")
	@PreAuthorize("hasAnyRoles('admin','shop', 'analysis', 'affiliate')")
	public ProductEditDTO findProduct(@PathVariable("productId") Long productId){
		
		return productService.findProduct(productId);
		
	}
	
	@PutMapping("/edit")
	@PreAuthorize("hasAnyRoles('admin','shop', 'affiliate')")
	public Boolean editProduct(@RequestBody ProductEditDTO productEditDTO) {
		 
		Preconditions.checkArgument(productEditDTO.getId() != null, "参数信息不完整...");
		
		productService.editProduct(productEditDTO);
		
		return Boolean.TRUE;
	}
	
	@PutMapping("/{productId}/copy")
	@PreAuthorize("hasAnyRoles('admin','shop', 'affiliate')")
	public Boolean copyProduct(@PathVariable("productId") Long productId) {
		 
		productService.copyProduct(productId);
		
		return Boolean.TRUE;
	}
	
	@PutMapping("/sets")
	@PreAuthorize("hasAnyRoles('admin','shop', 'affiliate')")
	public Boolean productSets(@RequestBody ProductSetEditDTO productSetEditDTO) {
		 
		Preconditions.checkArgument(productSetEditDTO.getProductId() != null, "参数信息不完整...");
		
		productService.productSets(productSetEditDTO);
		
		return Boolean.TRUE;
	}
	
	@PostMapping("/attributevalue")
	@PreAuthorize("hasAnyRoles('admin','shop', 'affiliate')")
	public Boolean addProductAttributeValue(@RequestBody ProductAttributeValueCreateDTO productAttributeValueCreateDTO) {
		 
		Preconditions.checkArgument(productAttributeValueCreateDTO.getProductId() != null, "参数信息不完整,产品ID不存在...");
		Preconditions.checkArgument(productAttributeValueCreateDTO.getAttributeId() != null, "参数信息不完整,属性ID不存在...");
		Preconditions.checkArgument(StrUtil.isNotBlank(productAttributeValueCreateDTO.getAttributeValueText()), "参数信息不完整,属性值不存在...");
		
		productService.addProductAttributeValue(productAttributeValueCreateDTO);
		
		return Boolean.TRUE;
	}
	
	@PutMapping("/batchEdit")
	@PreAuthorize("hasAnyRoles('admin','shop', 'affiliate')")
	public Boolean batchEditProduct(@RequestBody List<ProductBatchEditDTO> productBatchEditDTOs) {
		 
		productService.batchEditProduct(productBatchEditDTOs);
		
		return Boolean.TRUE;
	}
	
	@DeleteMapping("/{productId}")
	@PreAuthorize("hasAnyRoles('admin','shop', 'affiliate')")
	public Boolean deleteProduct(@PathVariable("productId") Long productId){
		
		productService.deleteProduct(productId);
		
		return Boolean.TRUE;
	}
	
	@PutMapping("/{productId}/up")
	@PreAuthorize("hasAnyRoles('admin','shop', 'affiliate')")
	public Boolean upProduct(@PathVariable("productId") Long productId) {
		
		productService.upProduct(productId);
		
		return Boolean.TRUE;
	}
	
	@PutMapping("/ups")
	@PreAuthorize("hasAnyRoles('admin','shop', 'affiliate')")
	public Boolean upProducts(@RequestBody List<Long> productIds) {
		
		for (Long productId : productIds) {
			try {
				productService.upProduct(productId);
			}catch (Exception e) {
				log.error(e.getMessage());
				e.printStackTrace();
			}
		}
		
		return Boolean.TRUE;
	}
	
	@PutMapping("/downs")
	@PreAuthorize("hasAnyRoles('admin','shop', 'affiliate')")
	public Boolean downProducts(@RequestBody List<Long> productIds) {
		
		for (Long productId : productIds) {
			try {
				productService.downProduct(productId);
			}catch (Exception e) {
				log.error(e.getMessage());
				e.printStackTrace();
			}
		}
		
		return Boolean.TRUE;
	}
	
	@PutMapping("/price/exchange/{exchangeRate}")
	public Boolean exchangeProductPrice(@PathVariable("exchangeRate") BigDecimal exchangeRate) {
		
		productService.exchangeProductPrice(exchangeRate);
		
		return Boolean.TRUE;
	}
	
	
	@GetMapping("/{productId}/comments")
	public List<ProductComments> searchComments(@PathVariable("productId") Long productId){
		return productService.searchComments(productId);
	}
	
	@PostMapping("/comments")
	public Boolean persitComments(@RequestBody ProductComments productComments) {
		productService.persistComments(productComments) ;
		
		return Boolean.TRUE;
	}
	
	@DeleteMapping("/comments")
	public Boolean deleteComments(@RequestBody List<Long> productIds) {
		productService.deleteComments(productIds);
		return Boolean.TRUE;
	}
}
